package ffte.evaluate.cases

import scala.util.Random._
import scala.collection.mutable.Map
import ffte.algorithm.Prime
import spinal.core._
import ffte.property.getShiftMethod

/**
 * FFT Test Case Configuration and Parameters Object
 *
 * Provides predefined and generated test case configurations for FFT implementations.
 * This object defines comprehensive test coverage including various FFT sizes,
 * scaling parameters, and special cases to validate algorithm correctness and
 * hardware performance characteristics.
 *
 * Features:
 * - Predefined test cases for common FFT sizes (2-2048 points)
 * - Prime number FFT configurations for prime factorization algorithms
 * - Extended random test generation for comprehensive validation
 * - Scaling parameter optimization for fixed-point arithmetic
 * - Support for power-of-2 and composite FFT sizes
 *
 * @example
 * // Get scaling for 64-point FFT
 * val scaling = FFTCase.cases(64)  // Returns 3
 *
 * // Get comprehensive test set
 * val allCases = FFTCase.full     // All FFT sizes 2-4096
 *
 * @see [[ffte.evaluate.cases.Sim]] for test execution framework
 */
object FFTCase {

    /** Additional special test cases for comprehensive validation */
    val some = List(1800,1379,1013,1151,1447,396,89,1723,1021,467,1910,5120,4096,8192,6400)

    /**
     * Gets the optimal scaling parameter for a given FFT size.
     *
     * Uses the configured shift method to determine the appropriate scaling
     * for fixed-point arithmetic based on FFT size and algorithm requirements.
     *
     * @param n FFT size
     * @return Recommended scaling shift value
     */
    def shift(n:Int) = getShiftMethod(n)

    /**
     * Prime number FFT configurations.
     *
     * Maps prime numbers to their optimal scaling parameters for testing
     * prime factorization algorithms and Winograd FFT implementations.
     */
    val prime = (for(i <- 1 until 20) yield {
            val n=Prime.primeList(i)
            val s = shift(n)
            (n->s)
    }).toMap

    /**
     * Basic FFT test case configurations.
     *
     * Covers fundamental FFT sizes including small primes, powers of 2,
     * and common composite numbers for initial validation.
     */
    val basic = prime ++ Map(
            2    -> 1,    // Smallest FFT
            28   -> 3,    // 4*7 composite
            58   -> 4,    // 2*29 prime composite
            70   -> 4,    // 2*5*7 composite
            68   -> 4,    // 4*17 composite
            42   -> 3,    // 2*3*7 composite
            46   -> 4,    // 2*23 prime composite
            25   -> 3,    // 5^2 prime power
            21   -> 3,    // 3*7 composite
            24   -> 3,    // 8*3 composite
            9    -> 2,    // 3^2 prime power
            27   -> 3,    // 3^3 prime power
            56   -> 4,    // 8*7 composite
            65   -> 4,    // 5*13 composite
            91   -> 4,    // 7*13 composite
            80   -> 4,    // 16*5 composite
            98   -> 4,    // 2*7^2 composite
            77   -> 4,    // 7*11 composite
            90   -> 4,    // 2*3^2*5 composite
            63   -> 4,    // 9*7 composite
            4    -> 1,    // 2^2 power of 2
            8    -> 2,    // 2^3 power of 2
            16   -> 2,    // 2^4 power of 2
            32   -> 3,    // 2^5 power of 2
            64   -> 3     // 2^6 power of 2
        )

    /**
     * Extended test case configurations.
     *
     * Includes larger FFT sizes and power-of-2 implementations for comprehensive
     * validation of scaling parameters and performance characteristics.
     */
    val cases = basic ++ Map(
            128  -> 4,    // 2^7 power of 2
            256  -> 4,    // 2^8 power of 2
            512  -> 5,    // 2^9 power of 2
            1024 -> 5,    // 2^10 power of 2
            2048 -> 6,    // 2^11 power of 2
            1440 -> 6,    // 32*45 composite
            1600 -> 6,    // 40*40 composite
            1920 -> 6,    // 64*30 composite
            800  -> 5,    // 32*25 composite
            640  -> 5,    // 128*5 composite
            720  -> 5,    // 16*45 composite
            121  -> 4,    // 11^2 prime power
            105  -> 4     // 3*5*7 composite
        ) ++  (for(n <- some) yield {
            // Calculate scaling as half of bit-width rounded up
            val s = (log2Up(n)+1)/2
            (n->s)
        })

    /**
     * Extended test set with additional random cases.
     *
     * Generates comprehensive test coverage including:
     * - Large prime numbers from the prime list
     * - Random composite numbers up to 2050
     *
     * @return Extended map of FFT sizes to scaling parameters
     */
    def extend =  cases ++  (for(i <- 21 until 310) yield {
            val n=Prime.primeList.reverse(i)
            val s = shift(n)
            (n->s)
        }) ++
        (for(i<- 0 until 290) yield {
            val n = Math.round(nextDouble()*2048).toInt+2
            val k = Prime.repesent(n).keySet.max
            val s = shift(n)
            (n->s)
        })

    /**
     * Comprehensive test case set for complete validation.
     *
     * Includes all FFT sizes from 2 to 2050, plus larger power-of-2
     * implementations up to 65536. This provides exhaustive coverage
     * for algorithm validation and performance testing.
     *
     * Features:
     * - All integer sizes 2-2050
     * - Power-of-2 sizes up to 65536
     * - Optimal scaling for each size
     *
     * @return Complete map of FFT sizes to scaling parameters
     */
    val full = (for(n <- 2 until 2050) yield {
        val s = shift(n)
        (n->s)
    }).toMap ++ (for(i <- 12 until 17) yield{
        val n = 1<<i  // Power of 2: 4096, 8192, 16384, 32768, 65536
        val s = shift(n)
        (n->s)
    })
}